﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using MyCommon.Helper;
using MyExtension.Authorizations;
using MyIServices;
using MyModels;
using MyModels.Models;
using MyModels.ViewModels;
using MyServices;
using Newtonsoft.Json.Linq;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;

namespace MyApi.Controllers
{
    /// <summary>
    /// 登录
    /// </summary>
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class LoginController : BaseApiController
    {
        private readonly ISysUserInfoServices _sysUserInfo;
        private readonly PermissionRequirement _required;
        private readonly IRoleModulePermissionService _roleModulePermissionService;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="sysUserInfo"></param>
        /// <param name="required"></param>
        public LoginController(ISysUserInfoServices sysUserInfo,PermissionRequirement required,IRoleModulePermissionService roleModulePermissionService)
        {
            _sysUserInfo = sysUserInfo;
            _required = required;
            _roleModulePermissionService = roleModulePermissionService;
        }

        /// <summary>
        /// 登录获取 Token
        /// </summary>
        /// <param name="loginModel"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<MessageModel<TokenInfoViewModel>> GetJwtToken(LoginModel loginModel)
        {
            if (string.IsNullOrEmpty(loginModel.UserName) ||string.IsNullOrEmpty(loginModel.Password))
            {
                return Fail<TokenInfoViewModel>("用户名或密码不能为空");
            }

            loginModel.Password = MD5Helper.MD5Encrypt32(loginModel.Password);
            var user = await _sysUserInfo.Query(i=>i.LoginName == loginModel.UserName&&i.LoginPwd==loginModel.Password &&i.IsDeleted==false);

            if (user.Count > 0)
            {
                var userRole = await _sysUserInfo.GetUserRoleNameStr(loginModel.UserName, loginModel.Password);
                //如果是基于用户的授权策略，这里要添加用户;如果是基于角色的授权策略，这里要添加角色
                var claims = new List<Claim>
                {
                    new Claim(ClaimTypes.Name, loginModel.UserName),
                    new Claim(JwtRegisteredClaimNames.Jti, user.FirstOrDefault()!.Id.ToString()),
                    new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.DateToTimeSpan()),
                    new Claim(ClaimTypes.Expiration,
                        DateTime.Now.AddSeconds(_required.Expiration.TotalSeconds).ToString())
                };
                claims.AddRange(userRole.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));

                var data = await _roleModulePermissionService.RoleModuleMap();
                var list = (from item in data
                            where item.IsDeleted == false
                            orderby item.Id
                            select new PermissionItem
                            {
                                Url = item.Modules?.LinkUrl!,
                                Role = item.Role?.Name?.ObjToString()!,
                            }).ToList();

                _required.Permissions = list;

                var token = JwtToken.BuildJwtToken(claims.ToArray(), _required);
                return Success(token, "获取成功");
            }
            else
            {
                return Fail<TokenInfoViewModel>("认证失败");
            }
        }

        /// <summary>
        /// 刷新Token
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<MessageModel<TokenInfoViewModel>> ReferenceToken(string token="")
        {
            if (string.IsNullOrWhiteSpace(token)) { return Fail<TokenInfoViewModel>("Token 无效，请重新登录"); }
            
            var tokenModel = JwtToken.SerializeToken(token);
            if (tokenModel != null&&JwtToken.customSafeVerify(token)&&tokenModel.Uid>0) {
                var user  = await _sysUserInfo.QueryById(tokenModel.Uid);
                var value = User.Claims.SingleOrDefault(i=>i.Type==JwtRegisteredClaimNames.Iat)?.Value;
                if (value != null&&user.CriticalModifyTime>value.ObjToDate()) {
                    return Fail<TokenInfoViewModel>("很抱歉,授权已失效,请重新授权！");
                }

                if(user!=null&&!(value != null && user.CriticalModifyTime > value.ObjToDate()))
                {
                    var userRole = await _sysUserInfo.GetUserRoleNameStr(user.LoginName,user.LoginPwd);
                    var claims = new List<Claim>() { 
                        new Claim(ClaimTypes.Name,user.LoginName),
                        new Claim(JwtRegisteredClaimNames.Jti, tokenModel.Uid.ObjToString()),
                        new Claim(JwtRegisteredClaimNames.Iat,  DateTime.Now.DateToTimeSpan()),
                        new Claim(ClaimTypes.Expiration,
                            DateTime.Now.AddSeconds(_required.Expiration.TotalSeconds).ToString())
                    };

                    claims.AddRange(userRole.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));

                    var referenceToken = JwtToken.BuildJwtToken(claims.ToArray(),_required);
                    return Success(referenceToken, "获取成功");
                }
            }

            return Fail<TokenInfoViewModel>("认证失败");
        }
    }

    /// <summary>
    /// 用户登录model
    /// </summary>
    public class LoginModel
    {
        /// <summary>
        /// 用户名
        /// </summary>
        public string? UserName { get; set; }
        /// <summary>
        /// 密码
        /// </summary>
        public string? Password { get; set; }
    }
}
